﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using IronCow.UnitTests.Mock;
using NUnit.Framework.SyntaxHelpers;

namespace IronCow.UnitTests
{
    [TestFixture]
    public class TestTasks
    {
        private MockRtm Rtm;

        [SetUp]
        public void SetUp()
        {
            Rtm = new MockRtm();
            Rtm.AddSuccessResponse("rtm.lists.getList",
                new MockListsResponsePart()
                {
                    new MockListResponsePart(100653, "Inbox", TaskListFlags.Locked),
                    new MockListResponsePart(387549, "High Priority", TaskListFlags.Smart, "(priority:1)"),
                    new MockListResponsePart(987654321, "New List"),
                    new MockListResponsePart(100654, "Personal"),
                    new MockListResponsePart(100655, "Study"),
                    new MockListResponsePart(100656, "Work"),
                    new MockListResponsePart(100657, "Sent", TaskListFlags.Locked)
                });
        }

        [TearDown]
        public void TearDown()
        {
            Rtm = null;
        }

        [Test]
        public void TestGetTasks()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                    {
                        new MockTaskSeriesResponsePart(123456789, "Get Bananas")
                        {
                            new MockTaskResponsePart(987654321)
                        }
                    }
                });

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(1, list.Tasks.Count);

            Task task = list.Tasks[0];
            Assert.IsTrue(task.IsSynced);
            Assert.AreEqual("987654321", task.Id);
            Assert.AreEqual("123456789", task.SeriesId);
            Assert.AreEqual("Get Bananas", task.Name);
            Assert.AreEqual(DateTime.Today, task.Created);
            Assert.AreEqual(DateTime.Today, task.Modified);
            Assert.AreEqual(DateTime.Today, task.Added);
            Assert.AreEqual(TaskPriority.None, task.Priority);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestAddTask()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                });
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.add",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });

            Task task = new Task("Get Bananas");
            Assert.IsFalse(task.IsSynced);

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(0, list.Tasks.Count);
            list.Tasks.Add(task);
            Assert.IsTrue(task.IsSynced);
            Assert.AreEqual(1, list.Tasks.Count);
            Assert.AreEqual("Get Bananas", task.Name);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestAddTaskWithOfflineDueDate()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                });
            Rtm.AddSuccessResponse("rtm.settings.getList", new MockUserSettingsResponsePart());
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.add",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setDueDate",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });

            Task task = new Task();
            task.Name = "Get Bananas";
            task.FuzzyDueDateTime = new FuzzyDateTime(new DateTime(1978, 1, 8), false);
            Assert.IsFalse(task.IsSynced);

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(0, list.Tasks.Count);
            list.Tasks.Add(task);
            Assert.IsTrue(task.IsSynced);
            Assert.AreEqual(1, list.Tasks.Count);
            Assert.AreEqual("Get Bananas", task.Name);
            Assert.AreEqual("01/08/78", task.Due);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestAddTaskWithOfflineUrl()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                });
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.add",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setURL",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });

            Task task = new Task();
            task.Name = "Get Bananas";
            task.Url = "http://www.banana.com";
            Assert.IsFalse(task.IsSynced);

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(0, list.Tasks.Count);
            list.Tasks.Add(task);
            Assert.IsTrue(task.IsSynced);
            Assert.AreEqual(1, list.Tasks.Count);
            Assert.AreEqual("Get Bananas", task.Name);
            Assert.AreEqual("http://www.banana.com", task.Url);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestAddTaskWithOfflineUrlAndDueDate()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                });
            Rtm.AddSuccessResponse("rtm.settings.getList", new MockUserSettingsResponsePart());
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.add",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setDueDate",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setURL",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                        {
                            Due = new DateTime(1978, 1, 8)
                        }
                    }
                });

            Task task = new Task();
            task.Name = "Get Bananas";
            task.Due = new DateTime(1978, 1, 8).ToString("MM/dd/yyyy");
            task.Url = "http://www.banana.com";
            Assert.IsFalse(task.IsSynced);

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(0, list.Tasks.Count);
            list.Tasks.Add(task);
            Assert.IsTrue(task.IsSynced);
            Assert.AreEqual(1, list.Tasks.Count);
            Assert.AreEqual("Get Bananas", task.Name);
            Assert.AreEqual("01/08/78", task.Due);
            Assert.AreEqual("http://www.banana.com", task.Url);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestAddOfflineInitializedTask()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                });
            Rtm.AddSuccessResponse("rtm.settings.getList", new MockUserSettingsResponsePart());
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.add",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setDueDate",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas")
                    {
                        new MockTaskResponsePart(123456789)
                        {
                            Due = new DateTime(1978, 1, 8)
                        }
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setPriority",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas", "http://en.wikipedia.org/wiki/Banana")
                    {
                        new MockTaskResponsePart(123456789)
                        {
                            Due = new DateTime(1978, 1, 8),
                            Priority = TaskPriority.One
                        }
                    }
                });
            Rtm.AddSuccessResponse("rtm.tasks.setURL",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(987654321, "Get Bananas", "http://en.wikipedia.org/wiki/Banana")
                    {
                        new MockTaskResponsePart(123456789)
                        {
                            Due = new DateTime(1978, 1, 8)
                        }
                    }
                });

            Task task = new Task();
            task.Name = "Get Bananas";
            task.FuzzyDueDateTime = new FuzzyDateTime(new DateTime(1978, 1, 8), false);
            task.Url = "http://en.wikipedia.org/wiki/Banana";
            task.Priority = TaskPriority.One;
            Assert.IsFalse(task.IsSynced);

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(0, list.Tasks.Count);
            list.Tasks.Add(task);
            Assert.IsTrue(task.IsSynced);
            Assert.AreEqual(1, list.Tasks.Count);
            Assert.AreEqual("Get Bananas", task.Name);
            Assert.AreEqual("01/08/78", task.Due);
            Assert.AreEqual("http://en.wikipedia.org/wiki/Banana", task.Url);
            Assert.AreEqual(TaskPriority.One, task.Priority);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestSetDueDate()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                    {
                        new MockTaskSeriesResponsePart(123456789, "Get Bananas")
                        {
                            new MockTaskResponsePart(987654321)
                        }
                    }
                });
            Rtm.AddSuccessResponse("rtm.settings.getList", new MockUserSettingsResponsePart());
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.setDueDate",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(123456789, "Get Coffee")
                    {
                        new MockTaskResponsePart(987654321)
                        {
                            Due = new DateTime(2006, 5, 9)
                        }
                    }
                });

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(1, list.Tasks.Count);

            Task task = list.Tasks[0];
            Assert.IsTrue(task.IsSynced);
            task.Due = new DateTime(2006, 5, 9).ToString("MM/dd/yy");
            Assert.AreEqual("05/09/06", task.Due);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestSetUrl()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                    {
                        new MockTaskSeriesResponsePart(123456789, "Get Bananas")
                        {
                            new MockTaskResponsePart(987654321)
                        }
                    }
                });
            Rtm.AddTimelineResponse();
            Rtm.AddSuccessResponse("rtm.tasks.setURL",
                new MockTaskListResponsePart(987654321)
                {
                    new MockTaskSeriesResponsePart(123456789, "Get Coffee")
                    {
                        Url = "http://www.coffee.com",
                        NestedParts = { new MockTaskResponsePart(987654321) }
                    }
                });

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(1, list.Tasks.Count);

            Task task = list.Tasks[0];
            Assert.IsTrue(task.IsSynced);
            task.Url = "http://www.coffee.com";
            Assert.AreEqual("http://www.coffee.com", task.Url);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestAmericanDateFormating()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                    {
                        new MockTaskSeriesResponsePart(123456789, "Get Bananas")
                        {
                            new MockTaskResponsePart(987654321)
                            {
                                Due = new DateTime(2008, 11, 02)
                            }
                        }
                    }
                });
            Rtm.AddSuccessResponse("rtm.settings.getList",
                new MockUserSettingsResponsePart("Canada/Vancouver", DateFormat.American, TimeFormat.TwelveHours));

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(1, list.Tasks.Count);
            Task task = list.Tasks[0];
            Assert.AreEqual("11/02/08", task.Due);

            Rtm.EnsureAllResponsesUsed();
        }

        [Test]
        public void TestEuropeanDateFormating()
        {
            Rtm.AddSuccessResponse("rtm.tasks.getList",
                new MockTasksResponsePart()
                {
                    new MockTaskListResponsePart(987654321)
                    {
                        new MockTaskSeriesResponsePart(123456789, "Get Bananas")
                        {
                            new MockTaskResponsePart(987654321)
                            {
                                Due = new DateTime(2008, 11, 02)
                            }
                        }
                    }
                });
            Rtm.AddSuccessResponse("rtm.settings.getList",
                new MockUserSettingsResponsePart("Canada/Vancouver", DateFormat.European, TimeFormat.TwentyFourHours));

            TaskList list = Rtm.TaskLists[2];
            Assert.AreEqual(1, list.Tasks.Count);
            Task task = list.Tasks[0];
            Assert.AreEqual("02/11/08", task.Due);

            Rtm.EnsureAllResponsesUsed();
        }
    }
}
